//先载入一个模块配置文件，成功后，再载入需要的模块
//Common中包含了一些通用函数，比如判断js文件是否存在等。
//注意Element中define(['vue']),所以对vue引用不能使用首字大写

/*
todo:
  块标题定义*
  新增行 *
  鼠标以上显示操作按钮，默认消失 *
  删除*,复制*，上移*，下移*
    上下移动后，弹出选择的文本内容没有变化*
    上下移动后，图片选择的张数没有改变*
  弹出选择 *
  图片
    如果图片结果为空，自动点击选择文件*
    文件上传成功后，按钮文字显示图片张数*
    预览有问题 *
    传递默认值过来*

  文件 *
  弹框表单录入
    无默认值无子记录字段*，有默认值无子记录字段*，无默认值有子记录字段*，有默认值有子记录字段*
    上下移动测试*
    复杂控件（弹出选择等）测试,选中后无反应(默认值中没有指定compName字段的值，导致computed监听失效)*
    确认回调*
  图片控件还是有闪烁现象 *
    组件内增加一个接收通知的方法,上下移动时发送通知给组件,处理通知时修改filelist
    该模式可以用来处理popup等显示文字问题.
    为每个组件增加一个接口valueChanged 是否需要进行联动修改 ,上下移动或者修改时,value改变后导致的一些后续变动都写在这里
  输入联动的自定义动作 *
  验证
  界面美化

*/
require(['Resource/Script/requireJs/_require.config.js?v='+Math.random()],function(){
  require(['vue','Common','axios'],function(vue,Common,axios){
    //模板变量预处理
    var title=varTemplate.title || '主从表单';
    var row = varTemplate.row;
    // var mainFormItems = varTemplate.mainFormItems;
    // var sonFormItems = varTemplate.sonFormItems;
    // var rules = varTemplate.rules;
    var sonKey = varTemplate.sonKey;
    // var action = varTemplate.action;
    var callbacks = [];

    //用来放置表单项的缓存,无法直接修改opt.data中的变量，所以通过这个缓存来修改
    var _FormItems_ = null;
    var _FormRules_ = null;
    var _FormAction_ = null;
    // var _VueRoot_ = null;
    //如果传入的是空对象,会转换为空数组
    if(!varTemplate.row || Array.isArray(varTemplate.row)) {
      varTemplate.row = {};
    }
    var opt = {
      el: '#div1',
      name:'compMain',
      data: function() {
        return {
          'formWidthCol':'',
          'formHeight':'500',
          'formTitle':title,
          'mainFormItems':_FormItems_,
          'sonFormItems':_SonFormItems_,
          'urlRemoveSon':_RemoveSonAction_,
          'row':varTemplate.row,
          //记录集中代表子表记录的字段名
          // 'sonKey':varTemplate.sonKey,
          //子表记录编辑表单是否可见
          'dialogSonVisible':false,
          //子表列
          // 'columnsSon':columnsSon,
          //子表弹窗绑定的记录集,
          // 'rowSon':this.getEmptyRowSon(sonFormItems),
          //当前编辑的子表记录的index
          // 'indexSon':-1,
          //验证规则
          'rules':_FormRules_,
          //提交action
          'action':_FormAction_,
          //提交按钮的可点击状态
          'disableSubmit':false,
          //所有表单元素的自定义事件的回调集合
          'callbacks':[],
          //子记录列表中除了修改删除外的按钮
          // 'otherButtons':sonButtons,
          //dropdown-men是否显示,dropdown显示时,不隐藏菜单
          // 'showDropdown':false,
          //当前显示dropdown的是第几行
          // 'showDropdownIndex':-1,
          //前三个默认显示的操作按钮
          // 'defaultEditButtons':defaultEditButtons,
          //从第4个开始后面的操作按钮
          // 'moreEditButtons':moreEditButtons,
          //每行功能按钮的可用图标
          // 'defaultEditButtonsIcons':['el-icon-edit','el-icon-delete','el-icon-edit-outline'],
          //其他组件,
          'otherComps':[],
          //是否显示子表记录列表的上移和下移按钮
          // 'showUpDown':true,
          //是否隐藏新增按钮
          // 'hideButtonAddSon':varTemplate.hideButtonAddSon||false,
          //保存成功后返回地址
          // 'targetUrl':varTemplate.targetUrl||null,
          //是否显示子表的上下移动按钮
          sonUpdown : varTemplate.sonUpdown,
          //右上角菜单
          menuRightTop : varTemplate.menuRightTop,
        }
      },
      methods : {
        //判断某个对象是否存在指定属性
        isset : Common.isset,
        //右上角菜单点击事件
        //当前记录作为参数传入
        handleTopRightClick : function(v) {
          this.callFunc(v,[this.row]);
        },
        //控件值改变了修改记录的值
        handleInput : function(row,key,val){
          if(row[key]) row[key]=val;
          else {
            vue.set(row,key,val);
          }
          // row[item.name]=arguments[0]
        },
        //字表记录中的组件值改变触发改变字表记录
        handleSonInput : function({row:row,key:key,val:val,sonKey:sonKey}) {
          if(Common.isset(row,key)) {
            row[key] = val;
          } else {
            vue.set(row,key,val);
          }
          //某些情况下，改变了录入数据，但是不刷新，需要强制刷新才可以
          this.$root.$refs['sonTable'][sonKey].doLayout();
        },

        //调试用方法
        test : function(rule, value, callback) {
          console.log(arguments);
          // return callback(new Error('年龄不能为空'));
        },
        //鼠标移上显示操作按钮
        handelMouseOverRow : function(row, column, cell, event) {
          if(!row.hasOwnProperty('__showButton')) {
            vue.set(row,'__showButton',true);
          } else {
            row.__showButton = true;
          }
        },
        //鼠标移出隐藏操作按钮
        handelMouseLeaveRow : function(row, column, cell, event) {
          if(this.showDropdown) return;
          row.__showButton = false;
        },

        //增加子表记录
        handleAddSon : function(keySon) {
          var   len = this.row[keySon].length;
          this.row[keySon].push({});
        },
        //表格的删除按钮点击事件
        handleDelete : function(keySon,scope) {
          var row = scope.row;
          var index = scope.$index;
          // debugger;
          //阻止事件冒泡
          this.$confirm('确认删除吗?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            //ajax从后台删除记录,todo
            var url=this.urlRemoveSon;
            if(!url) {
              console.error(`必须在后台的${varTemplate.urlGetItems}方法返回的json对象中定义urlRemoveSon属性`);
              return;
            }
            var params = {row:row,keySon:keySon};
            this.$http.post(url,params)
            .then((res)=>{
              if(!res.data.success) {
                this.$notify.error({
                  'title':'删除失败',
                  'message':res.data.msg ? res.data.msg : 'response.data.success not found'
                });
                dump(res);
                return false;
              }
              this.$notify.success({
                title:'成功',
                message:res.data.msg,
              });
              //从数据集中删除当前记录
              this.row[keySon].splice(index,1);
            }).catch(function (error) {
              dump(error);
            });

          }).catch(() => {
            return false;
          });
          // console.log(arguments);
        },
        //复制
        handleCopy : function(keySon,scope) {
          var row = scope.row;
          var index = scope.$index;

          var r = JSON.parse(JSON.stringify(row));
          //删除id属性,避免重复id出现
          delete r.id
          r.__showButton = false;
          this.row[keySon].splice(index+1,0,r);

          // 响应copy后面的事情
          let methodName = `${keySon}:afterCopy`;
          if(this.callbacks[methodName]) {
            this.callbacks[methodName].apply(this,[this.row[keySon][index+1]]);
          }
        },
        //上移
        handleMoveup : function(keySon,scope) {
          var row = scope.row;

          var index = scope.$index;

          if(index==0) return;
          this.row[keySon].splice(index,1);
          this.row[keySon].splice(index-1,0,row);

          // this.row[keySon][index].__showButton = false;
          this.row[keySon][index-1].__showButton = false;

          //如果是图片控件,需要交换图片的file-list属性,
          //file-list属性不能在组件内部修改,内部修改回导致图片闪烁.
          for(var k in this.$refs) {
            if(k.substring(0,4)!='son_') continue;
            var items = this.$refs[k];
            if(items[0].fld.type!='comp-image-popover') continue;
            var temp0 = this.$refs[`son_${items[0].fld.name}_${index}`][0].value ||[];
            var temp1 = this.$refs[`son_${items[0].fld.name}_${index-1}`][0].value||[];
            this.$refs[`son_${items[0].fld.name}_${index}`][0].fileList = temp1;
            this.$refs[`son_${items[0].fld.name}_${index}`][1].fileList = temp1;
            this.$refs[`son_${items[0].fld.name}_${index-1}`][0].fileList = temp0;
            this.$refs[`son_${items[0].fld.name}_${index-1}`][1].fileList = temp0;
          }
        },

        //下移
        handleMovedown : function(keySon,scope) {
          // scope.row.money=300;return;
          var row = scope.row;

          var index = scope.$index;

          if(index==this.row[keySon].length-1) return;
          this.row[keySon].splice(index,1);
          this.row[keySon].splice(index+1,0,row);

          //如果是图片控件,需要交换图片的file-list属性,
          //file-list属性不能在组件内部修改,内部修改回导致图片闪烁.
          //后期可优化为向组件发送通知,组件内些代码处理通知,便于封装.
          for(var k in this.$refs) {
            if(k.substring(0,4)!='son_') continue;
            var items = this.$refs[k];
            if(items[0].fld.type!='comp-image-popover') continue;
            var temp0 = this.$refs[`son_${items[0].fld.name}_${index}`][0].value ||[];
            var temp1 = this.$refs[`son_${items[0].fld.name}_${index+1}`][0].value||[];
            this.$refs[`son_${items[0].fld.name}_${index}`][0].fileList = temp1;
            this.$refs[`son_${items[0].fld.name}_${index}`][1].fileList = temp1;
            this.$refs[`son_${items[0].fld.name}_${index+1}`][0].fileList = temp0;
            this.$refs[`son_${items[0].fld.name}_${index+1}`][1].fileList = temp0;
          }

          this.row[keySon][index+1].__showButton = false;
        },


        checkSon : function(son) {
          if(son.length==0) {
            this.$message('子表记录必须不为空','error');
            return false;
          }
          //这里可加入用户自定义的beforeSubmit回调函数,
          //一般这里处理子表记录的验证规则
          if(this.callbacks['beforeSubmit']) {
            return this.callbacks['beforeSubmit'].apply(this,[this.row]);
          }
          return true;
        },
        //表单提交事件
        submitForm(formName) {
          this.$refs[formName].validate((valid) => {
            if (!valid) {
              console.log('error submit!!');
              return false;
            }

            //检查子表记录,
            //因为存在多个子表记录,这里暂时忽略
            // if(!this.checkSon(this.row[this.sonKey])) {
            //   return;
            // }

            //这里可加入用户自定义的beforeSubmit回调函数,
            //一般这里处理子表记录的验证规则
            if(this.callbacks['beforeSubmit']) {
              var ret = this.callbacks['beforeSubmit'].apply(this,[this.row]);
              if(!ret) return false;
            }

            this.disableSubmit = true;
            // console.log('form submit fired,params',this.row);
            this.$http.post(this.action,this.row).then((res)=>{

              setTimeout(() => {
                this.disableSubmit = false;
              }, 2000);

              if(!res.data.success) {
                // this.$message('response.data.success not found','error');
                this.$notify.error({
                  'title':'保存失败',
                  'message':res.data.msg ? res.data.msg : 'response.data.success not found'
                });
                console.log(res);
                return false;
              }
              // this.disableSubmit = false;
              if(res.data.msg){
                this.$notify.success({
                  title:'成功',
                  message:res.data.msg,
                  time:1500,
                });
              }
              
              // this.$message(message:res.data.msg,'success');

              if(this.callbacks['afterSubmitForm']) {
                var ret = this.callbacks['afterSubmitForm'].apply(this,[this.row,res.data]);
              }else{
                var url = res.data.targetUrl ? res.data.targetUrl : this.targetUrl;
                if(url) {
                  setTimeout(function(){
                      window.location.href = url;
                  },this.redirectTime);
                }
              }

            }).catch(function (error) {
              console.log(error);
              // this.$message('请求失败,检查url或者其他设置','error');
              this.$notify.error({
                'title':'请求失败',
                'message':'请求失败,检查url或者其他设置'
              });

              this.disableSubmit = false;
            });
          });
        },
        resetForm(formName) {
          this.$refs[formName].resetFields();
        },
        //调用sonTpl中的方法
        callFunc(methodName,arg) {
          if(arg && !Array.isArray(arg)) {
            console.warn(`调用sonTpl中的${methodName}方法，参数必须为数组`);
            return;
          }
          if(!this.callbacks[methodName]) {
            console.warn(`未在sonTpl中发现${methodName}方法`);
            return;
          }
          return this.callbacks[methodName].apply(this,arg);
        },
      },
      mounted: function(){
        dump('_mainSonForm mounted',this);
        // this.formItems=_FormItems_;
        this.rules=_FormRules_;
        //载入sonTpl
        var _this = this;
        Common.setSontpl.apply(this,[varTemplate,function(){
          //处理表单验证对象,将自定义验证方法由字符串改为函数指针
          for (var k in _this.rules) {
            _this.rules[k].forEach((rule,index)=>{
              if(!rule.validator) return;
              if(!_this.callbacks.hasOwnProperty(rule.validator)) {
                alert(`sontpl中未对 ${rule.validator} 进行定义`);
                return;
              }
              rule.validator = _this.callbacks[rule.validator];
            });
          }
        }]);

		    //默认一行，新增的时候
        _this.$nextTick(() => {
          _SonFormItems_.forEach(function(item){
            // console.log(item);
            if(!_this.row[item.key].length && item.buttonVisble.buttonAdd!=false && item.buttonVisble.editColumn!=false){
              _this.handleAddSon(item.key);
            }
          });
        })

        // Common.setSontpl(varTemplate);
        // var _this = this;
        // require([_tplPath_+'/'+varTemplate.sonTpl],function(ev){
        //   _this.callbacks = ev;

        //   //处理表单验证对象,将自定义验证方法由字符串改为函数指针
        //   for (var k in _this.rules) {
        //     _this.rules[k].forEach((rule,index)=>{
        //       if(!rule.validator) return;
        //       if(!_this.callbacks.hasOwnProperty(rule.validator)) {
        //         alert(`sontpl中未对 ${rule.validator} 进行定义`);
        //         return;
        //       }
        //       rule.validator = _this.callbacks[rule.validator];
        //     });
        //   }

        //   if(ev.main) {
        //     ev.main.apply(_this);
        //   }
        // },function(err){
        //   console.log('sontpl不存在')
        // });
      },
    };

    //ajax获得表单参数,覆盖配置文件的 compnents 属性
    var prm = new Promise( function(resolve,reject) {
      //如果存在 formItems 模板变量，直接赋值，否则ajax获取
      if(varTemplate.formItems) {
        return resolve({data:varTemplate.formItems});
      }
      var act = varTemplate.urlGetItems || 'GetFormItems';
      var url=`?controller=${varTemplate.controller}&action=${act}`;
      if(varTemplate.fullUrlGetItems){
        url = varTemplate.fullUrlGetItems;
      }
      var params={};
      axios.post(url,params).then((res)=>{
        if(!res.data.success) {
          dump('get form items failed',res.data);
          return false;
        }
        return resolve(res);
      });
    });
    prm.then(function(res){
      //开始处理components属性
      _FormItems_ = res.data.mainFormItems;
      _SonFormItems_ = res.data.sonFormItems;
      _FormRules_ = res.data.rules||null;
      _FormAction_ = res.data.action||'';
      _RemoveSonAction_ = res.data.urlRemoveSon||'';

      //处理每个子信息都含有按钮组显示配置，减少tpl文件里的判断出错，没有则给个{}
      _SonFormItems_.forEach(function(item,index){
        item.buttonVisble = item.buttonVisble || {};
      });
      // console.log(_SonFormItems_);

      //确保子表字段都存在
      var row = varTemplate.row;
      for(var i=0;_SonFormItems_[i];i++) {
        var k = _SonFormItems_[i].key;
        if(!row[k]) {
          vue.set(row,k,[]);
        }
      }
      //根据表单项配置,设置默认值
      for(var i=0;_FormItems_[i];i++) {
        var key = _FormItems_[i].name;
        if(Common.isset(row,key)) continue;
        vue.set(row,key,_FormItems_[i].value);
      }

      //使用eval动态加载异步组件
      //测试时，发现el-table的bug，如果使用异步组件，无法在列中显示自定义组件，所以这里改为提前载入
      opt.components = {};

      var temp = {};
      //先处理系统级别组件
      var arrComps = ['comp-card'];
      for(var i=0;arrComps[i];i++) {
        // temp = temp +`'${arrComps[i]}':resolve=>require(['_vue!pathComponent/${arrComps[i]}'], resolve),`;
        temp[arrComps[i]] = `_vue!pathComponent/${arrComps[i]}`;
      }

      //主表单组件
      var arrCompsMain = res.data.mainFormItems;
      for(var i=0;arrCompsMain[i];i++) {
        // temp = temp +`'${items[i].type}':resolve=>require(['_vue!pathComponent/${items[i].type}'], resolve),`;
        temp[arrCompsMain[i].type]=`_vue!pathComponent/${arrCompsMain[i].type}`;
      }

      //子表单组件
      var arrCompsSon = res.data.sonFormItems;
      for(var i=0;arrCompsSon[i];i++) {
        var items = arrCompsSon[i].items;
        for(var j=0;items[j];j++) {
          temp[items[j].type] = `_vue!pathComponent/${items[j].type}`;
        }

        //将row中的字表记录强制变为对象，防止空数组导致问题
        var _son = row[arrCompsSon[i].key];
        if(!_son) continue;
        for(var j=0;_son[j];j++) {
          if(Array.isArray(_son[j])) _son[j]={};
        }
      }
      // dump(arrCompsSon);dump(temp);

      //使用vue的异步机制进行载入，
      //但是mainsonform.tpl模板中使用了el-table组件，所以不能在这里进行异步组件声明，
      //而应该改为在mount事件中使用require语法进行批量预载入。
      // var tempStr = "";
      // for(var k in temp) {
      //   tempStr = tempStr +`'${k}':resolve=>require(['_vue!pathComponent/${k}'], resolve),`;
      // }
      // opt.components = eval(`({${tempStr}})`);
      // var app = new vue(opt);

      //使用requireJs的异步机制进行载入，
      var temp1 = [];
      for(var k in temp) {
        temp1.push(temp[k]);
      }
      require(temp1,function(){
        var i=0;
        for(var k in temp) {
          opt.components[k] = arguments[i++];
        }
        var app = new vue(opt);
      });
    },function(err){
        dump('prm reject fired',err);
    });

    /*//ajax获得表单参数,覆盖配置文件的 compnents 属性
    var act = varTemplate.urlGetItems || 'GetFormItems';
    var url=`?controller=${varTemplate.controller}&action=${act}`;
    if(varTemplate.fullUrlGetItems){
      url = varTemplate.fullUrlGetItems;
    }

    var params={};
    axios.post(url,params).then((res)=>{
      if(!res.data.success) {
        dump('get form items failed',res.data);
        return false;
      }
      //开始处理components属性
      _FormItems_ = res.data.mainFormItems;
      _SonFormItems_ = res.data.sonFormItems;
      _FormRules_ = res.data.rules||null;
      _FormAction_ = res.data.action||'';
      _RemoveSonAction_ = res.data.urlRemoveSon||'';

      //处理每个子信息都含有按钮组显示配置，减少tpl文件里的判断出错，没有则给个{}
      _SonFormItems_.forEach(function(item,index){
        item.buttonVisble = item.buttonVisble || {};
      });
      // console.log(_SonFormItems_);

      //确保子表字段都存在
      var row = varTemplate.row;
      for(var i=0;_SonFormItems_[i];i++) {
        var k = _SonFormItems_[i].key;
        if(!row[k]) {
          vue.set(row,k,[]);
        }
      }
      //根据表单项配置,设置默认值
      for(var i=0;_FormItems_[i];i++) {
        var key = _FormItems_[i].name;
        if(Common.isset(row,key)) continue;
        vue.set(row,key,_FormItems_[i].value);
      }

      //使用eval动态加载异步组件
      //测试时，发现el-table的bug，如果使用异步组件，无法在列中显示自定义组件，所以这里改为提前载入
      opt.components = {};

      var temp = {};
      //先处理系统级别组件
      var arrComps = ['comp-card'];
      for(var i=0;arrComps[i];i++) {
        // temp = temp +`'${arrComps[i]}':resolve=>require(['_vue!pathComponent/${arrComps[i]}'], resolve),`;
        temp[arrComps[i]] = `_vue!pathComponent/${arrComps[i]}`;
      }

      //主表单组件
      var arrCompsMain = res.data.mainFormItems;
      for(var i=0;arrCompsMain[i];i++) {
        // temp = temp +`'${items[i].type}':resolve=>require(['_vue!pathComponent/${items[i].type}'], resolve),`;
        temp[arrCompsMain[i].type]=`_vue!pathComponent/${arrCompsMain[i].type}`;
      }

      //子表单组件
      var arrCompsSon = res.data.sonFormItems;
      for(var i=0;arrCompsSon[i];i++) {
        var items = arrCompsSon[i].items;
        for(var j=0;items[j];j++) {
          temp[items[j].type] = `_vue!pathComponent/${items[j].type}`;
        }

        //将row中的字表记录强制变为对象，防止空数组导致问题
        var _son = row[arrCompsSon[i].key];
        if(!_son) continue;
        for(var j=0;_son[j];j++) {
          if(Array.isArray(_son[j])) _son[j]={};
        }
      }
      // dump(arrCompsSon);dump(temp);

      //使用vue的异步机制进行载入，
      //但是mainsonform.tpl模板中使用了el-table组件，所以不能在这里进行异步组件声明，
      //而应该改为在mount事件中使用require语法进行批量预载入。
      // var tempStr = "";
      // for(var k in temp) {
      //   tempStr = tempStr +`'${k}':resolve=>require(['_vue!pathComponent/${k}'], resolve),`;
      // }
      // opt.components = eval(`({${tempStr}})`);
      // var app = new vue(opt);

      //使用requireJs的异步机制进行载入，
      var temp1 = [];
      for(var k in temp) {
        temp1.push(temp[k]);
      }
      require(temp1,function(){
        var i=0;
        for(var k in temp) {
          opt.components[k] = arguments[i++];
        }
        var app = new vue(opt);
      });
    });*/
  })
});


